package Java_Concurrency_in_Practice.implicit_lock_which;

/**
 * 内置锁
 * @author xiangke
 *
 */
public class ImplicitLockTest {

    private Object lock = new Object();

	static ImplicitLockTest test = new ImplicitLockTest();
	
	public static void main(String[] args) {
	    useSameLock();

	    useSameLock2();
	}

    /**
     * 静态方法使用的锁和使用类字节码加锁使用的是同一把锁
     */
    private static void useSameLock2() {
        test.synchronizedBlockOnClass(2000);
        synchronizedMethodOnClass(2000);
    }

    /**
     * 方法上用 synchronized 修饰 </br>
     * 和方法体内用 synchronized(this) </br>
     * 以及 方法体内用 synchronized(this class instance)</br>
     * 实际上是用的同一把锁
     */
    private static void useSameLock() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.synchronizedMethodOnThis(1000);
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                test.synchronizedBlockOnThis(1000);
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                test.synchronizedBlockOnInstance(1000);
            }
        }).start();
    }


    public void synchronizedBlockOnObject(long executeTime) {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " -> start synchronizedBlockOnObject");
            doSomething(executeTime);
            System.out.println(Thread.currentThread().getName() + " -> end synchronizedBlockOnObject");
        }
    }

    public void synchronizedBlockOnThis(long executeTime) {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + " -> start synchronizedBlockOnThis");
            doSomething(executeTime);
            System.out.println(Thread.currentThread().getName() + " -> end synchronizedBlockOnThis");
        }
    }
    
    public void synchronizedBlockOnInstance(long executeTime) {
        synchronized (test) {
            System.out.println(Thread.currentThread().getName() + " -> start synchronizedBlockOnInstance");
            doSomething(executeTime);
            System.out.println(Thread.currentThread().getName() + " -> end synchronizedBlockOnInstance");
        }
    }
    

    public void synchronizedBlockOnClass(long executeTime) {
        synchronized (ImplicitLockTest.class) {
            System.out.println(Thread.currentThread().getName() + " -> start synchronizedBlockOnClass");
            doSomething(executeTime);
            System.out.println(Thread.currentThread().getName() + " -> end synchronizedBlockOnClass");
        }
    }

    public synchronized void synchronizedMethodOnThis(long executeTime) {
        System.out.println(Thread.currentThread().getName() + " -> start synchronizedMethodOnThis");
        doSomething(executeTime);
        System.out.println(Thread.currentThread().getName() + " -> end synchronizedMethodOnThis");
    }

    public static synchronized void synchronizedMethodOnClass(long executeTime) {
        System.out.println(Thread.currentThread().getName() + " -> start synchronizedMethodOnClass");
        doSomething(executeTime);
        System.out.println(Thread.currentThread().getName() + " -> end synchronizedMethodOnClass");
    }

    private static void doSomething(long executeTime) {
        try {
            Thread.sleep(executeTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}